package com.whisperarts.financer.app.dialogs;

import static com.whisperarts.financer.model.account.Account.CATEGORY;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.forms.widgets.*;

import com.whisperarts.financer.adapters.CurrencyAdapter;
import com.whisperarts.financer.app.utils.DateUtils;
import com.whisperarts.financer.app.utils.UIUtils;
import com.whisperarts.financer.app.widgets.AmountComposite;
import com.whisperarts.financer.model.account.Account;
import com.whisperarts.financer.model.currency.Currency;

public class AddAccountDialog extends Dialog implements SelectionListener {

	protected Text textName, textNote;
	
	protected Combo comboCurrency;
	
	protected Label labelOpeningDate;

	private FormToolkit toolkit;

	private String shellTitle;	
	
	private Calendar openingDate;
	private int accountType;
	private String name, note;
	private Currency currency;

	private Button buttonCash, buttonCard, buttonWeb, buttonBank, buttonOther;
	private final List<Button> buttons = new ArrayList<Button>();
	
	private final Shell parentShell;

	private Account account;

	private Form form;

	private Section section;
	
	protected final CurrencyAdapter adapter;

	protected AmountComposite amountComposite;

	public AddAccountDialog(Shell parentShell, int accountType) {
		super(parentShell);
		this.accountType = accountType;
		this.parentShell = parentShell;
		adapter = new CurrencyAdapter();
	}

	@Override
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		initNew();
		newShell.setText(shellTitle);
	}

	private void initNew() {
		shellTitle = "Add new account";
		openingDate = Calendar.getInstance();
	}

	@Override
	protected Control createDialogArea(Composite parent) {
		toolkit = new FormToolkit(parent.getDisplay());
		
		form = toolkit.createForm(parent);
		form.setText("New account");
		toolkit.decorateFormHeading(form);
		toolkit.paintBordersFor(form.getBody());

		TableWrapLayout layout = new TableWrapLayout();
		layout.numColumns = 1;
		form.getBody().setLayout(layout);

		Composite composite = toolkit.createComposite(form.getBody());

		toolkit.adapt(composite);
		toolkit.createLabel(composite, "Account type:");

		Composite radioComposite = toolkit.createComposite(composite, SWT.NONE);
		radioComposite.setLayout(new GridLayout(5, true));

		buttonCash = toolkit.createButton(radioComposite, CATEGORY[0], SWT.RADIO);
		buttonCard = toolkit.createButton(radioComposite, CATEGORY[1], SWT.RADIO);
		buttonWeb = toolkit.createButton(radioComposite, CATEGORY[2], SWT.RADIO);
		buttonBank = toolkit.createButton(radioComposite, CATEGORY[3], SWT.RADIO);
		buttonOther = toolkit.createButton(radioComposite, CATEGORY[4], SWT.RADIO);

		initRadioListeners();
		
		GridLayout glayout = new GridLayout(2, false);
		composite.setLayout(glayout);

		toolkit.createLabel(composite, "&Name:");
		textName = new Text(composite, SWT.BORDER);
		textName.setLayoutData(new GridData(GridData.FILL, GridData.FILL,
				true, false));

		toolkit.createLabel(composite, "&Opening amount:");
		Composite amount = toolkit.createComposite(composite);
		amount.setLayout(new GridLayout(2, false));
		amount.setLayoutData(new GridData(GridData.FILL, GridData.FILL,
				true, false));
		
		amountComposite = new AmountComposite(amount, SWT.NONE, adapter.getCurrencySymbols()[0], true);
		amountComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		
		comboCurrency = new Combo(amount, SWT.READ_ONLY);
		comboCurrency.setItems(adapter.getCurrencyCodes());
		comboCurrency.select(0);
		comboCurrency.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				amountComposite.setSymbolLabel(adapter.getCurrencyByCode(comboCurrency.getText()).getSymbol());
			}
		});
		
		toolkit.createLabel(composite, "&Note:");		
		textNote = new Text(composite, SWT.BORDER);
		textNote.setLayoutData(new GridData(GridData.FILL, GridData.FILL,
				true, false));

		
		int expanded = Section.TITLE_BAR | Section.EXPANDED;
		createExpandableSectionWithTable("Additional info", expanded);

		Composite bottom = toolkit.createComposite(form.getBody());
		bottom.setLayout(new GridLayout(2, true));
		toolkit.createLabel(bottom, "");
		
		
		Composite opening = toolkit.createComposite(bottom);
		opening.setLayout(new GridLayout(2, true));		
		toolkit.createLabel(opening, "&Opening date:");	
		labelOpeningDate = toolkit.createLabel(opening, DateUtils.dateToString(openingDate));
		
		fillData();
		
		return composite;
	}

	private TableViewer createExpandableSectionWithTable(String title, int style) {
        /**
         * Create an expandable section with title, description, style
         * (expanded) and column span
         */
        Section section = createSection(title, style);

        // Create the composite as a part of the form.
        Composite sectionClient = toolkit.createComposite(section);

        /**
         * Give the widgets a flat look
         */
        sectionClient.setData(FormToolkit.KEY_DRAW_BORDER,
                FormToolkit.TEXT_BORDER);
        toolkit.paintBordersFor(sectionClient);

        /**
         * Use the forms HTML like table layout for the contents of the
         * expandable section
         */
        TableWrapLayout layout = new TableWrapLayout();
        layout.numColumns = 2;

        sectionClient.setLayout(layout);

        /**
         * Add contents to the section client. A table is wrapped on a
         * table viewer to use label and content providers
         */
        Table table = toolkit.createTable(sectionClient, SWT.FILL);

        TableWrapData td = new TableWrapData(TableWrapData.FILL_GRAB);
        td.colspan = 2;
        td.heightHint = 100;

        table.setLayoutData(td);

        /**
         * Sets the client of this expandable composite. The client must
         * not be null and must be a direct child of this container.
         */
        section.setClient(sectionClient);

        return new TableViewer(table);
    }
	
	/**
     * Create a expandable form section. It uses a Layout data in
     * conjunction with HTMLTableLayout.
     */
    private Section createSection(String title, int style) {
        
    	section = toolkit.createSection(form.getBody(), style);

        if (title != null)
            section.setText(title);

        TableWrapData td = new TableWrapData(TableWrapData.FILL_GRAB);
        td.colspan = 1;
        section.setLayoutData(td);

        return section;
    }
	
	protected void fillData() {
		
	}
	
	private void initRadioListeners() {
		buttonCash.addSelectionListener(this);
		buttonCard.addSelectionListener(this);
		buttonWeb.addSelectionListener(this);
		buttonBank.addSelectionListener(this);
		buttonOther.addSelectionListener(this);
		buttons.add(buttonCash);
		buttons.add(buttonCard);
		buttons.add(buttonWeb);
		buttons.add(buttonBank);
		buttons.add(buttonOther);
		buttons.get(accountType).setSelection(true);
	}

	@Override
	protected void okPressed() {		
		name = textName.getText();
		
		if ("".equals(name)) {
			MessageDialog.openError(getShell(), "Invalid Title",
			"Title field must not be blank.");
			return;
		}
		
		if (isNameExists(name)) {
			MessageDialog.openError(parentShell, "Error", "Account " + name + " already exist. Choose another name");
			return;
		}
	
		currency = adapter.getCurrencyByCode(comboCurrency.getText());
		note = textNote.getText();
		
		createAccount();
		super.okPressed();
	}

	protected boolean isNameExists(String name) {
		if (UIUtils.checkAccountName(name)) {
			return true;
		}
		return false;
	}
	
	protected void createAccount() {
		account = getAccountToCreate();
		account.setName(name);
		account.setNote(note);
		account.setCurrency(currency);
		account.setDateOfCreation(openingDate);
		account.setAccountType(accountType);
		account.setOpeningAmount(amountComposite.getAmount());
	}

	protected Account getAccountToCreate() {
		return new Account();
	}

	public Account getAccount() {		
		return account;
	}

	@Override
	public void widgetSelected(SelectionEvent e) {
		accountType = buttons.indexOf(e.getSource());
	}

	@Override
	public void widgetDefaultSelected(SelectionEvent e) {
	}
}
